const fs = require('fs');
const chalk = require("chalk");
const admZip = require('adm-zip');
const recast = require("recast");
const compressing = require('compressing');
const pathutil = require('path');
const stat=fs.stat;

/**删除目录及子目录 */
function delFloder(path){
    return new Promise(async function(resolve,reject){
        /**1、判断目录是否存在，存在则删除 */
        try{
            if ((await fs.existsSync(path))) {
                let files = [];
                files = await fs.readdirSync(path);
                files.forEach(async function(file,index){
                    var curPath = path + "/" + file;
                    if( await fs.statSync(curPath).isDirectory()) {
                        await delFloder(curPath);
                    } else {
                        await fs.unlinkSync(curPath);
                    }
                });
                try{ 
                    await fs.rmdirSync(path);
                }catch(err){
                    await delFloder(path);
                }
                resolve();
            }else{
                resolve();
            }
        }catch(err){
            console.log("递归删除文件出错");
            console.log(err);
            reject(err);
        }
	});
}

/**
 * 复制文件夹下所有文件
 *  */
function copyFloder(src,dst){
    return new Promise(async function(resolve,reject){
        //读取目录
        fs.readdir(src,function(err,paths){
            if(err){
                throw err;
            }
            paths.forEach(async function(path){
                let _src=src+'/'+path;
                let _dst=dst+'/'+path;
                let readable;
                let writable;
                await stat(_src,async function(err,st){
                    if(err){
                        console.log(chalk.red("获取文件状态报错"));
                        console.log(err);
                        reject(err);
                    }
                    
                    if(await st.isFile()){
                        readable = await fs.createReadStream(_src);//创建读取流
                        writable = await fs.createWriteStream(_dst);//创建写入流
                        readable.pipe(writable);
                    }else if(await st.isDirectory()){
                        await exists(_src,_dst,copyFloder);
                    }
                });
            });
        }); 
        resolve();
    });
}

function exists(src,dst,callback){
    return new Promise(async function(resolve,reject){
        try{
            if(!(await fs.existsSync(dst))){
                await fs.mkdirSync(dst);
            }
            await callback(src,dst);
        }catch(err){
            console.log(chalk.red("复制深层文件时出错"));
            console.log(err);
            reject(err);
        }
    });
}

/**读取压缩包下的 project.conf.js 文件 */
async function readZipPorjectConf(zipfile,filename){
    return new Promise(async function(resolve,reject){
        try{
            let zipEnt = new admZip(zipfile);
            filename = filename.replace(/\\/g,'/');
            let conftext = zipEnt.readAsText(filename);
            if(!conftext){
                await resolve('');
                return this;
            }

            let plugMap = {};
            const ast = recast.parse(conftext);
            /**解析ast语法数 */
            let plugarr = ast.program.body[0].expression.right.properties;

            plugarr.forEach((arr)=>{
                let key = arr.key.name;
                let value = arr.value.value;
                if(key=='func'){
                    let funcelement = arr.value.elements;
                    let funcArr = putFunc(funcelement);
                    plugMap['func']=funcArr;
                }else{
                    plugMap[key]=value;
                }
            });
            resolve(plugMap);
        }catch(err){
            console.log(err);
            reject('读取配置文件报错');
        }
    });
}
/**解析ast的func */
function putFunc(funcelement){
    let funcArr = new Array();
    funcelement.forEach((arr)=>{
        let func = {};
        let funcast = arr.properties;
        funcast.forEach((arrf)=>{
            let key = arrf.key.name;
            let value = arrf.value.value;
            func[key] = value;
        });
        funcArr.push(func);
    });
    return funcArr;
}

/**判断压缩包的文件是否存在*/
function readZipFile(zipfile,filename){
    var zipEnt = new admZip(zipfile);
    filename = filename.replace(/\\/g,'/');
    let file = zipEnt.readAsText(filename);

    if(!file){
        return false;
    }else{
        return true;
    }
}

/**解压文件 */
function unzipFile(file, path) {
    return new Promise(async function (resolve, reject) {
        try {
            /**判断文件是否存在 */
            if (await fs.existsSync(file) == false) {
                console.log(chalk.red("上传后解压时发现压缩包不存在:" + file));
                reject('上传后解压时发现压缩包不存在');
            }

            /**删除现有同名目录 */
            await delFloder(path);

            /**解压文件 */
            await compressing.zip.uncompress(file, path)
                .then(() => {
                    resolve('解压成功');
                })
                .catch(err => {
                    console.log(chalk.red(err));
                    reject(err);
                })
        } catch (err) {
            console.log(err);
            reject("上传/解压压缩包后台程序报错");
        }
    });
}


exports.copyFloder = copyFloder;
exports.delFloder = delFloder;
exports.readZipFile = readZipFile;
exports.readZipPorjectConf = readZipPorjectConf;
exports.unzipFile = unzipFile;